{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "6f678e62-7bcb-4405-86ae-dce94f494303",
      "metadata": {
        "id": "6f678e62-7bcb-4405-86ae-dce94f494303"
      },
      "source": [
        "# Efficient Multi-Head Attention Implementations"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b742938a-4bfc-4527-a1f1-d5963508967d",
      "metadata": {
        "id": "b742938a-4bfc-4527-a1f1-d5963508967d"
      },
      "source": [
        "This code notebook compares different ways to implement causal multi-head attention used in decoder-style LLMs like GPT, Llama, etc."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "7898551e-f582-48ac-9f66-3632abe2a93f",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "7898551e-f582-48ac-9f66-3632abe2a93f",
        "outputId": "2ddf0145-94d3-4490-8087-d1ffeb6f30ab"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "PyTorch version: 2.2.1+cu121\n",
            "Running on cuda\n"
          ]
        }
      ],
      "source": [
        "import torch\n",
        "\n",
        "torch.manual_seed(123)\n",
        "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
        "print(f\"PyTorch version: {torch.__version__}\")\n",
        "print(f\"Running on {device}\")\n",
        "\n",
        "batch_size = 8\n",
        "context_len = 1024\n",
        "embed_dim = 768\n",
        "embeddings = torch.randn((batch_size, context_len, embed_dim), device=device)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2f9bb1b6-a1e5-4e0a-884d-0f31b374a8d6",
      "metadata": {
        "id": "2f9bb1b6-a1e5-4e0a-884d-0f31b374a8d6"
      },
      "source": [
        "## 1) CausalAttention MHA wrapper class from chapter 3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "297c93ed-aec0-4896-bb89-42c4b294d3d1",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "297c93ed-aec0-4896-bb89-42c4b294d3d1",
        "outputId": "ae6d707f-eae8-467a-ed4d-a88051bf776f"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 9216])\n"
          ]
        }
      ],
      "source": [
        "from ch03 import MultiHeadAttentionWrapper as Ch03_MHA_Wrapper\n",
        "\n",
        "mha_ch03_wrapper = Ch03_MHA_Wrapper(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False\n",
        ").to(device)\n",
        "\n",
        "out = mha_ch03_wrapper(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "21930804-b327-40b1-8e63-94dcad39ce7b",
      "metadata": {
        "id": "21930804-b327-40b1-8e63-94dcad39ce7b"
      },
      "source": [
        "## 2) The multi-head attention class from chapter 3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4ee6a61b-d25c-4a0c-8a59-f285544e3710",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4ee6a61b-d25c-4a0c-8a59-f285544e3710",
        "outputId": "5df88462-8b1a-4b1f-ce71-3909ad2ca9c2"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 768])\n"
          ]
        }
      ],
      "source": [
        "from ch03 import MultiHeadAttention as Ch03_MHA\n",
        "\n",
        "mha_ch03 = Ch03_MHA(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False\n",
        ").to(device)\n",
        "\n",
        "out = mha_ch03(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73cd11da-ea3b-4081-b483-c4965dfefbc4",
      "metadata": {
        "id": "73cd11da-ea3b-4081-b483-c4965dfefbc4"
      },
      "source": [
        "## 3) An alternative multi-head attention with combined weights"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1fa1a5ea-eaff-4d2d-aaf0-b34cdb6fd4dd",
      "metadata": {
        "id": "1fa1a5ea-eaff-4d2d-aaf0-b34cdb6fd4dd"
      },
      "source": [
        "- The code for the `MultiHeadAttentionAlt` class below is based on code that was kindly shared by [Rayed Bin Wahed](https://github.com/rasbt/LLMs-from-scratch/discussions/51)\n",
        "- The main difference between the `MultiHeadAttentionAlt` class and the `MultiHeadAttention` class used in chapter 3 is that `MultiHeadAttentionAlt` uses a single weight matrix, `self.qkv = nn.Linear(d_in, 3 * d_out, bias=qkv_bias)` instead of separate weight matrices:\n",
        "\n",
        "  - `self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)`\n",
        "  - `self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)`\n",
        "  - `self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)`\n",
        "\n",
        "- Here, `self.qkv` combines all three weight matrices `self.W_query`, `self.W_key`, and `self.W_value` to carry out the query, key, and value computation in a single step\n",
        "- Using `q, k, v = qkv.unbind(0)`, we obtain the individual query, key, and value tensors, which are then used similarly to the query, key, and value tensors in the `MultiHeadAttention` class in chapter 3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9a6bd0a2-f27c-4602-afa0-c96cd295c1a6",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "9a6bd0a2-f27c-4602-afa0-c96cd295c1a6",
        "outputId": "1240afaf-139a-4d01-ddac-4a186ff4a4fd"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 768])\n"
          ]
        }
      ],
      "source": [
        "import torch.nn as nn\n",
        "\n",
        "\n",
        "class MultiHeadAttentionCombinedQKV(nn.Module):\n",
        "    def __init__(self, d_in, d_out, num_heads, block_size, dropout=0.0, qkv_bias=False):\n",
        "        super().__init__()\n",
        "\n",
        "        assert d_out % num_heads == 0, \"embed_dim is indivisible by num_heads\"\n",
        "\n",
        "        self.num_heads = num_heads\n",
        "        self.block_size = block_size\n",
        "        self.head_dim = d_out // num_heads\n",
        "\n",
        "        self.qkv = nn.Linear(d_in, 3 * d_out, bias=qkv_bias)\n",
        "        self.proj = nn.Linear(d_in, d_out)\n",
        "        self.dropout = nn.Dropout(dropout)\n",
        "\n",
        "        self.register_buffer(\n",
        "            \"mask\", torch.triu(torch.ones(block_size, block_size), diagonal=1)\n",
        "        )\n",
        "\n",
        "    def forward(self, x):\n",
        "        batch_size, num_tokens, embed_dim = x.shape\n",
        "\n",
        "        # (b, num_tokens, embed_dim) --> (b, num_tokens, 3 * embed_dim)\n",
        "        qkv = self.qkv(x)\n",
        "\n",
        "        # (b, num_tokens, 3 * embed_dim) --> (b, num_tokens, 3, num_heads, head_dim)\n",
        "        qkv = qkv.reshape(batch_size, num_tokens, 3, self.num_heads, self.head_dim)\n",
        "\n",
        "        # (b, num_tokens, 3, num_heads, head_dim) --> (3, b, num_heads, num_tokens, head_dim)\n",
        "        qkv = qkv.permute(2, 0, 3, 1, 4)\n",
        "\n",
        "        # (3, b, num_heads, num_tokens, head_dim) -> 3 times (b, num_head, num_tokens, head_dim)\n",
        "        queries, keys, values = qkv.unbind(0)\n",
        "\n",
        "        # (b, num_heads, num_tokens, head_dim) --> (b, num_heads, num_tokens, num_tokens)\n",
        "        attn_scores = queries @ keys.transpose(-2, -1)\n",
        "        attn_scores = attn_scores.masked_fill(\n",
        "            self.mask.bool()[:num_tokens, :num_tokens], -torch.inf\n",
        "        )\n",
        "\n",
        "        attn_weights = torch.softmax(attn_scores / keys.shape[-1]**-0.5, dim=-1)\n",
        "        attn_weights = self.dropout(attn_weights)\n",
        "\n",
        "        # (b, num_heads, num_tokens, num_tokens) --> (b, num_heads, num_tokens, head_dim)\n",
        "        context_vec = attn_weights @ values\n",
        "\n",
        "        # (b, num_heads, num_tokens, head_dim) --> (b, num_tokens, num_heads, head_dim)\n",
        "        context_vec = context_vec.transpose(1, 2)\n",
        "\n",
        "        # (b, num_tokens, num_heads, head_dim) --> (b, num_tokens, embed_dim)\n",
        "        context_vec = context_vec.reshape(batch_size, num_tokens, embed_dim)\n",
        "\n",
        "        context_vec = self.proj(context_vec)\n",
        "\n",
        "        return context_vec\n",
        "\n",
        "\n",
        "mha_combined_qkv = MultiHeadAttentionCombinedQKV(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False\n",
        ").to(device)\n",
        "\n",
        "out = mha_combined_qkv(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48a042d3-ee78-4c29-bf63-d92fe6706632",
      "metadata": {
        "id": "48a042d3-ee78-4c29-bf63-d92fe6706632"
      },
      "source": [
        "## 4) Multihead attention with PyTorch's scaled dot product attention"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f78e346f-3b85-44e6-9feb-f01131381148",
      "metadata": {
        "id": "f78e346f-3b85-44e6-9feb-f01131381148"
      },
      "source": [
        "- The implementation below uses PyTorch's [`scaled_dot_product_attention`](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html) function, which implements a memory-optimized version of self-attention calld [flash attention](https://arxiv.org/abs/2205.14135)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "1b8e5a0d-1f65-4a03-bf6e-723f0cc428f5",
      "metadata": {
        "id": "1b8e5a0d-1f65-4a03-bf6e-723f0cc428f5"
      },
      "outputs": [],
      "source": [
        "class MHAPyTorchScaledDotProduct(nn.Module):\n",
        "    def __init__(self, d_in, d_out, num_heads, block_size, dropout=0.0, qkv_bias=False):\n",
        "        super().__init__()\n",
        "\n",
        "        assert d_out % num_heads == 0, \"embed_dim is indivisible by num_heads\"\n",
        "\n",
        "        self.num_heads = num_heads\n",
        "        self.block_size = block_size\n",
        "        self.head_dim = d_out // num_heads\n",
        "        self.d_out = d_out\n",
        "\n",
        "        self.qkv = nn.Linear(d_in, 3 * d_out, bias=qkv_bias)\n",
        "        self.proj = nn.Linear(d_in, d_out)\n",
        "        self.dropout = dropout\n",
        "\n",
        "        self.register_buffer(\n",
        "            \"mask\", torch.triu(torch.ones(block_size, block_size), diagonal=1)\n",
        "        )\n",
        "\n",
        "    def forward(self, x):\n",
        "        batch_size, num_tokens, embed_dim = x.shape\n",
        "\n",
        "        # (b, num_tokens, embed_dim) --> (b, num_tokens, 3 * embed_dim)\n",
        "        qkv = self.qkv(x)\n",
        "\n",
        "        # (b, num_tokens, 3 * embed_dim) --> (b, num_tokens, 3, num_heads, head_dim)\n",
        "        qkv = qkv.reshape(batch_size, num_tokens, 3, self.num_heads, self.head_dim)\n",
        "\n",
        "        # (b, num_tokens, 3, num_heads, head_dim) --> (3, b, num_heads, num_tokens, head_dim)\n",
        "        qkv = qkv.permute(2, 0, 3, 1, 4)\n",
        "\n",
        "        # (3, b, num_heads, num_tokens, head_dim) -> 3 times (b, num_heads, num_tokens, head_dim)\n",
        "        queries, keys, values = qkv.unbind(0)\n",
        "\n",
        "        use_dropout = 0. if not self.training else self.dropout\n",
        "        context_vec = nn.functional.scaled_dot_product_attention(\n",
        "            queries, keys, values, attn_mask=None, dropout_p=use_dropout, is_causal=True)\n",
        "\n",
        "        # Combine heads, where self.d_out = self.num_heads * self.head_dim\n",
        "        context_vec = context_vec.transpose(1, 2).contiguous().view(batch_size, num_tokens, self.d_out)\n",
        "\n",
        "        return context_vec"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "fbc8ba92-3471-41cb-b1b2-4c0ef5be392b",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "fbc8ba92-3471-41cb-b1b2-4c0ef5be392b",
        "outputId": "83ef0a2f-3fe6-4123-c8de-f481f2a9e415"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 768])\n"
          ]
        }
      ],
      "source": [
        "mha_pytorch_scaled = MHAPyTorchScaledDotProduct(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False\n",
        ").to(device)\n",
        "\n",
        "out = mha_pytorch_scaled(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "351c318f-4835-4d74-8d58-a070222447c4",
      "metadata": {
        "id": "351c318f-4835-4d74-8d58-a070222447c4"
      },
      "source": [
        "## 5) Using PyTorch's torch.nn.MultiheadAttention"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74a6d060-6324-48fa-a35c-cb09f2a48965",
      "metadata": {
        "id": "74a6d060-6324-48fa-a35c-cb09f2a48965"
      },
      "source": [
        "- Below, we use PyTorch's [torch.nn.MultiheadAttention](https://pytorch.org/docs/stable/generated/torch.nn.MultiheadAttention.html) implementation"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "3799c7ef-3155-42c6-a829-f95656453ae0",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "3799c7ef-3155-42c6-a829-f95656453ae0",
        "outputId": "aabf134e-c9bc-474b-ee57-0c24b5fb604c"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 768])\n"
          ]
        }
      ],
      "source": [
        "import torch.nn as nn\n",
        "\n",
        "\n",
        "class MHAPyTorchClass(nn.Module):\n",
        "    def __init__(self, d_in, d_out, num_heads, block_size, dropout=0.0, qkv_bias=False, need_weights=True):\n",
        "        super().__init__()\n",
        "\n",
        "        self.block_size = block_size\n",
        "        self.multihead_attn = nn.MultiheadAttention(\n",
        "            embed_dim=d_out,\n",
        "            num_heads=num_heads,\n",
        "            dropout=dropout,\n",
        "            bias=qkv_bias,\n",
        "            add_bias_kv=qkv_bias,\n",
        "            batch_first=True,\n",
        "        )\n",
        "\n",
        "        self.need_weights = need_weights\n",
        "        self.proj = nn.Linear(d_out, d_out)\n",
        "        self.register_buffer(\"mask\", torch.triu(torch.ones(block_size, block_size), diagonal=1).bool())\n",
        "\n",
        "    def forward(self, x):\n",
        "        batch_size, num_tokens, _ = x.shape\n",
        "\n",
        "        # Ensure attn_mask is compatible with expected shape and `batch_first=True`\n",
        "        # No need to manually adjust for num_heads; ensure it's right for the sequence\n",
        "        if self.block_size >= num_tokens:\n",
        "            attn_mask = self.mask[:num_tokens, :num_tokens]\n",
        "        else:\n",
        "            attn_mask = self.mask[:self.block_size, :self.block_size]\n",
        "\n",
        "        # attn_mask broadcasting will handle batch_size dimension implicitly\n",
        "        attn_output, _ = self.multihead_attn(\n",
        "            x, x, x, attn_mask=attn_mask, need_weights=self.need_weights\n",
        "        )\n",
        "\n",
        "        output = self.proj(attn_output)\n",
        "\n",
        "        return output\n",
        "\n",
        "\n",
        "mha_pytorch_class_default = MHAPyTorchClass(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False\n",
        ").to(device)\n",
        "\n",
        "out = mha_pytorch_class_default(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a3953bff-1056-4de2-bfd1-dfccf659eee4",
      "metadata": {
        "id": "a3953bff-1056-4de2-bfd1-dfccf659eee4"
      },
      "source": [
        "## 6) Using PyTorch's torch.nn.MultiheadAttention with `scaled_dot_product_attention`"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d2164859-31a0-4537-b4fb-27d57675ba77",
      "metadata": {
        "id": "d2164859-31a0-4537-b4fb-27d57675ba77"
      },
      "source": [
        "- Set `need_weights` (default `True`) to need_weights=False so that MultiheadAttention uses `scaled_dot_product_attention` [according to the documentation](https://github.com/pytorch/pytorch/blob/71d020262793542974cf13b30f2a9099773f015c/torch/nn/modules/activation.py#L1096)\n",
        "\n",
        ">  need_weights: If specified, returns ``attn_output_weights`` in addition to ``attn_outputs``.\n",
        "            Set ``need_weights=False`` to use the optimized ``scaled_dot_product_attention``\n",
        "            and achieve the best performance for MHA.\n",
        "            Default: ``True``."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "4a4c2afe-5e1f-4bd7-a118-67031176f147",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4a4c2afe-5e1f-4bd7-a118-67031176f147",
        "outputId": "5b577a7c-4199-4e52-8d08-a0974a5a3685"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([8, 1024, 768])\n"
          ]
        }
      ],
      "source": [
        "mha_pytorch_class_noweights = MHAPyTorchClass(\n",
        "    d_in=embed_dim,\n",
        "    d_out=embed_dim,\n",
        "    block_size=context_len,\n",
        "    dropout=0.0,\n",
        "    num_heads=12,\n",
        "    qkv_bias=False,\n",
        "    need_weights=False # NEW!\n",
        ").to(device)\n",
        "\n",
        "out = mha_pytorch_class_noweights(embeddings)\n",
        "print(out.shape)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8877de71-f84f-4f6d-bc87-7552013b6301",
      "metadata": {
        "id": "8877de71-f84f-4f6d-bc87-7552013b6301"
      },
      "source": [
        "## Quick speed comparison (M1 Macbook Air CPU)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a97c0b2e-6593-49d8-98bc-2267b3aa610f",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "a97c0b2e-6593-49d8-98bc-2267b3aa610f",
        "outputId": "ebe635b2-5c03-4e9b-da3a-951d308acf7b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "1.15 s ± 86.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
          ]
        }
      ],
      "source": [
        "## 1) CausalAttention MHA wrapper class from chapter 3\n",
        "%timeit mha_ch03_wrapper(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "19db9c2c-8e75-431a-8eef-0b4d8284e6e6",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "19db9c2c-8e75-431a-8eef-0b4d8284e6e6",
        "outputId": "c6e7bcff-661c-45a6-da82-b1e3f89cf761"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "273 ms ± 3.63 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
          ]
        }
      ],
      "source": [
        "## 2) The multi-head attention class from chapter 3\n",
        "%timeit mha_ch03(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "aa526ee0-7a88-4f34-a49a-f8f97da83779",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "aa526ee0-7a88-4f34-a49a-f8f97da83779",
        "outputId": "92b634f8-43f8-468f-87a1-bb774b64c212"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "324 ms ± 17.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
          ]
        }
      ],
      "source": [
        "## 3) An alternative multi-head attention with combined weights\n",
        "%timeit mha_combined_qkv(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "cc2b4256-16d8-4c34-9fd0-d4b4af0e60fa",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "cc2b4256-16d8-4c34-9fd0-d4b4af0e60fa",
        "outputId": "80c6e314-0771-470e-b090-628984ce2d85"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "106 ms ± 598 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 4) Multihead attention with PyTorch's scaled dot product attention\n",
        "%timeit mha_pytorch_scaled(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0f209e70-ebb6-4a1a-b608-1ff42e41c01d",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0f209e70-ebb6-4a1a-b608-1ff42e41c01d",
        "outputId": "3cd37b53-04d4-4dd0-9450-6fc8ebaac083"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "351 ms ± 7.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
          ]
        }
      ],
      "source": [
        "## 5) Using PyTorch's torch.nn.MultiheadAttention\n",
        "%timeit mha_pytorch_class_default(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3f4968c2-8d40-4ab9-8dba-052b4f77d756",
      "metadata": {
        "tags": [],
        "id": "3f4968c2-8d40-4ab9-8dba-052b4f77d756",
        "outputId": "2e86bdb4-7fa0-4051-b000-4a2b591060a2"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "333 ms ± 14.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
          ]
        }
      ],
      "source": [
        "## 6) Using PyTorch's torch.nn.MultiheadAttention disabling `need_weights`\n",
        "%timeit mha_pytorch_class_noweights(embeddings)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a78ff594-6cc2-496d-a302-789fa104c3c9",
      "metadata": {
        "id": "a78ff594-6cc2-496d-a302-789fa104c3c9"
      },
      "source": [
        "## Quick speed comparison (Nvidia A100 GPU)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "707a2a14-a089-48a8-88aa-d328e1e0a9d0",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "707a2a14-a089-48a8-88aa-d328e1e0a9d0",
        "outputId": "07a711f6-f7ff-496c-ce16-be67308aeadf"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "41.1 ms ± 5.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 1) CausalAttention MHA wrapper class from chapter 3\n",
        "%timeit mha_ch03_wrapper(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "8686dd69-3655-40e4-a57b-a2c55532a010",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "8686dd69-3655-40e4-a57b-a2c55532a010",
        "outputId": "b0c29336-55e8-4194-89e4-9201f77e5375"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "6.58 ms ± 256 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 2) The multi-head attention class from chapter 3\n",
        "%timeit mha_ch03(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "2209d7df-e54b-4910-ae2b-c78cf684d9bf",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "2209d7df-e54b-4910-ae2b-c78cf684d9bf",
        "outputId": "ba357440-47d4-450d-b859-08031056ccf8"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "7.19 ms ± 590 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 3) An alternative multi-head attention with combined weights\n",
        "%timeit mha_combined_qkv(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "1075abe2-4839-4fd6-af3e-c09bb3651e26",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1075abe2-4839-4fd6-af3e-c09bb3651e26",
        "outputId": "b2126630-7fae-4c44-8180-226ff5509d78"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "2.37 ms ± 569 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 4) Multihead attention with PyTorch's scaled dot product attention\n",
        "%timeit mha_pytorch_scaled(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "868e3670-8edc-47bc-9e06-eb505e44dc9d",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "868e3670-8edc-47bc-9e06-eb505e44dc9d",
        "outputId": "453d9b7b-3f45-4907-b4fd-77d395534d6b"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "6.66 ms ± 301 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 5) Using PyTorch's torch.nn.MultiheadAttention\n",
        "%timeit mha_pytorch_class_default(embeddings)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "944870e6-de54-4e3b-a455-b8f21f6f92c8",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "944870e6-de54-4e3b-a455-b8f21f6f92c8",
        "outputId": "ccfe127c-c069-4dcd-f37d-ea6a40406955"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "4.52 ms ± 317 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
          ]
        }
      ],
      "source": [
        "## 6) Using PyTorch's torch.nn.MultiheadAttention disabling `need_weights`\n",
        "%timeit mha_pytorch_class_noweights(embeddings)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dabc6575-0316-4640-a729-e616d5c17b73",
      "metadata": {
        "id": "dabc6575-0316-4640-a729-e616d5c17b73"
      },
      "source": [
        "## Speed comparison (Nvidia A100 GPU) with warmup"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "29b63d3d-6d0b-43bb-9c68-d5514dc81000",
      "metadata": {
        "id": "29b63d3d-6d0b-43bb-9c68-d5514dc81000"
      },
      "outputs": [],
      "source": [
        "# CUDA benchmark code shared by Andrei Aksionov\n",
        "# and based on code from\n",
        "# https://github.com/cuda-mode/lectures/blob/main/lecture1/pytorch_square.py\n",
        "\n",
        "def time_pytorch_function(func, *input, num_repeats = 1_000):\n",
        "    # CUDA IS ASYNC so can't use python time module\n",
        "    start = torch.cuda.Event(enable_timing=True)\n",
        "    end = torch.cuda.Event(enable_timing=True)\n",
        "\n",
        "    # Warmup\n",
        "    for _ in range(5):\n",
        "        func(*input)\n",
        "    torch.cuda.synchronize()\n",
        "\n",
        "    start.record()\n",
        "    for _ in range(num_repeats):\n",
        "        func(*input)\n",
        "        torch.cuda.synchronize()\n",
        "    end.record()\n",
        "    torch.cuda.synchronize()\n",
        "    return start.elapsed_time(end) / num_repeats"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "\n",
        "embeddings_cuda = embeddings.to(torch.device(\"cuda\"))\n",
        "\n",
        "functions = {\n",
        "    \"1) MHA wrapper class\": mha_ch03_wrapper,\n",
        "    \"2) MHA Ch03\": mha_ch03,\n",
        "    \"3) MHA with combined QKV weights\": mha_combined_qkv,\n",
        "    \"4) MHA with PyTorch scaled_dot_product_attention\": mha_pytorch_scaled,\n",
        "    \"5) PyTorch MHA class defaults\": mha_pytorch_class_default,\n",
        "    \"6) PyTorch MHA with need_weights=False\": mha_pytorch_class_noweights\n",
        "}\n",
        "execution_times = [time_pytorch_function(fn, embeddings_cuda) for name,fn in functions.items()]\n",
        "\n",
        "\n",
        "# Plotting\n",
        "\n",
        "# Customize further for dark mode aesthetics\n",
        "plt.rcParams['figure.facecolor'] = '#121212'  # Dark figure background\n",
        "plt.rcParams['axes.facecolor'] = '#121212'    # Dark axes background\n",
        "plt.rcParams['axes.edgecolor'] = 'white'      # White axes border\n",
        "plt.rcParams['axes.labelcolor'] = 'white'     # White labels\n",
        "plt.rcParams['text.color'] = 'white'          # White text\n",
        "plt.rcParams['xtick.color'] = 'white'         # White x ticks\n",
        "plt.rcParams['ytick.color'] = 'white'         # White y ticks\n",
        "plt.rcParams['grid.color'] = '#444444'        # Lighter grid lines for contrast\n",
        "plt.rcParams['lines.linewidth'] = 2           # Thicker plot lines for visibility\n",
        "plt.rcParams['lines.markersize'] = 8          # Larger markers for visibility\n",
        "\n",
        "fig, ax = plt.subplots()\n",
        "bars = plt.bar(functions.keys(), execution_times)\n",
        "\n",
        "plt.ylabel('Execution time (ms)')\n",
        "plt.xticks(rotation=45, ha=\"right\")\n",
        "\n",
        "# Calculate new ylim with a margin\n",
        "max_execution_time = max(execution_times)\n",
        "upper_ylim = max_execution_time + 0.2 * max_execution_time  # Adding a 20% margin\n",
        "\n",
        "plt.ylim(0, upper_ylim)  # Setting new ylim\n",
        "\n",
        "# Annotate bars with execution times\n",
        "for bar in bars:\n",
        "    yval = bar.get_height()\n",
        "    plt.text(bar.get_x() + bar.get_width()/2, yval + (0.05 * upper_ylim), round(yval, 2), ha='center', va='bottom')\n",
        "\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.savefig(\"1.pdf\")\n",
        "plt.show()\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 488
        },
        "id": "CDJAPZaszaqx",
        "outputId": "47c9ef93-438e-4455-faef-7e253eaaaa8d"
      },
      "id": "CDJAPZaszaqx",
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {}
        }
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "gpuType": "A100",
      "machine_shape": "hm",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}